#ifndef GTL_ENTITIES_HEADER_GUARD
#define GTL_ENTITIES_HEADER_GUARD

#include "gtlCompilerSpecific.h"
#include "external_libs/eastl/include/eastl/vector.h"

namespace GTL
{
  namespace Entities
  {
    class Component;

    class ComponentUpdaterBase 
    {
    public:
      virtual uint32_t Update() = 0;
      virtual ~ComponentUpdaterBase() {}
    };

    class Component
    {
    public:
      uint32_t EntityID;
      uint32_t ComponentTypeID;
      virtual uint32_t GetComponentType() const = 0;
    protected:
      Component() {}
    };

    template <typename T>
    uint32_t UpdateComponents(eastl::vector<T*>& components);

    template <typename T>
    class ComponentUpdater : public ComponentUpdaterBase
    {
    public:
      eastl::vector<T*> Components;

      T* NewComponent(uint32_t entityID = 0)
      {
        T* comp = new T;
        comp->EntityID = entityID;
        Components.push_back(comp);
        return comp;
      }

      virtual uint32_t Update()
      {
        return UpdateComponents(Components);
      }

      virtual ~ComponentUpdater<T>() { }
    };

    /// This class doesn't need to really exist for each entity.
    /// We can just store the EntityID as an uint32 and it will work just as well.
    /// But it's useful when we need to store a list of all the components of an entity
    /// in the same place.
    class Entity
    {
    public:
      uint32_t EntityID;

      enum EntityError
      {
        OK,
        AlreadyAttached,
        NotAttached,
      };

      const eastl::vector<Component*> & GetComponents() const
      {
        return mComponents;
      }

      EntityError AttachComponent(Component* component)
      {
        for (size_t i = 0; i < mComponents.size(); i++)
          if (mComponents[i] == component)
            return AlreadyAttached;

        component->EntityID = EntityID;
        mComponents.push_back(component);

        return OK;
      }

      EntityError DetachComponent(Component* component)
      {
        for (size_t i = 0; i < mComponents.size(); i++)
          if (mComponents[i] == component)
          {
            component->EntityID = 0;
            mComponents.erase(mComponents.begin()+i);
            return OK;
          }

          return NotAttached;
      }
    private:
      eastl::vector<Component*> mComponents; /// this is only for lookup
    };
  }
}

#endif